#include "client.h"
#include <string>
#include <sstream>

using namespace std;

PacketHeader outPktHdr, inPktHdr;
MailHeader outMailHdr, inMailHdr;
char buffer[MaxMailSize];

int ClientCreateLock(char *name) {
	int randServ = rand() % numberOfServers;
  outPktHdr.to = randServ;
  outMailHdr.to = randServ;
  outMailHdr.from = myMachID;

  stringstream ss;
  char *message = new char[MaxMailSize];
  //int timet = time(NULL)%10000000;
  //ss << timet << " ";	//send the timestamp
  ss << "11 " << name;
  message = (char*)ss.str().c_str();
  
  outMailHdr.length = strlen(message) + 1;

  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message); 

    if ( !success ) {
      printf("Create Lock postOffice send failed. No server found.\n");
      return -1;
    }
	else {
		printf("Create Lock postOffice send succeeded!\n");
	}


  // Wait for the first message from the other machine
    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);
    // printf("Got \"%s\" from %d, box %d\n",buffer,inPktHdr.from,inMailHdr.from);

    /* PARSE THE INT FROM THE MESSAGE; LOCK INDEX */
	int lockSuccess = atoi(buffer);
	DEBUG('n', "Client: lockSuccess = %i\n", lockSuccess);

    fflush(stdout);

    return lockSuccess; // CHANGE TO: the parsed index when available
}

int ClientAcquireLock(char *name) {
	int randServ = rand() % numberOfServers;
  outPktHdr.to = randServ;
  outMailHdr.to = randServ;
  outMailHdr.from = myMachID;

  stringstream ss;
  char *message = new char[MaxMailSize];
  //int timet = time(NULL)%10000000;
  //ss << timet << " ";	//send the timestamp
  ss << "12 " << name;
  message = (char*)ss.str().c_str();

  outMailHdr.length = strlen(message) + 1;
  
  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Aquire Lock postOffice send failed. No server found.\n");
      return -1;
    }

    // Wait for the first message from the other machine
    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);
    // printf("Got \"%s\" from %d, box %d\n",buffer,inPktHdr.from,inMailHdr.from);

    /* PARSE THE INT FROM THE MESSAGE; SUCCESS OR FAIL (1 or 0) */
	int lockSuccess = atoi(buffer);
	DEBUG('n', "Client: lockSuccess = %i\n", lockSuccess);

    fflush(stdout);

    return lockSuccess; // CHANGE TO: 0 for lock not acquired or 1 when it is
}

int ClientReleaseLock(char *name) {
	int randServ = rand() % numberOfServers;
  outPktHdr.to = randServ;
  outMailHdr.to = randServ;
  outMailHdr.from = myMachID;

  stringstream ss;
  char *message = new char[MaxMailSize];
  //int timet = time(NULL)%10000000;
  //ss << timet << " ";	//send the timestamp
  ss << "13 " << name;
  message = (char*)ss.str().c_str();

  outMailHdr.length = strlen(message) + 1;

  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Release Lock postOffice send failed. No server found.\n");
      return -1;
    }

    // Wait for the first message from the other machine
    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);
    // printf("Got \"%s\" from %d, box %d\n",buffer,inPktHdr.from,inMailHdr.from);

    /* PARSE THE INT FROM THE MESSAGE; SUCCESS OR FAIL (1 or 0) */
	int lockSuccess = atoi(buffer);
	DEBUG('n', "Client: lockSuccess = %i\n", lockSuccess);

    fflush(stdout);

    return lockSuccess; // CHANGE TO: 0 for lock not released or 1 when it is
}

int ClientDeleteLock(char *name) {
	int randServ = rand() % numberOfServers;
  outPktHdr.to = randServ;
  outMailHdr.to = randServ;
  outMailHdr.from = myMachID;

  stringstream ss;
  char *message = new char[MaxMailSize];
  //int timet = time(NULL)%10000000;
  //ss << timet << " ";	//send the timestamp
  ss << "14 " << name;
  message = (char*)ss.str().c_str();

  outMailHdr.length = strlen(message) + 1;

  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Delete Lock postOffice send failed. No server found.\n");
      return -1;
    }

    // Wait for the first message from the other machine
    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);
    // printf("Got \"%s\" from %d, box %d\n",buffer,inPktHdr.from,inMailHdr.from);

    /* PARSE THE INT FROM THE MESSAGE; SUCCESS OR FAIL (1 or 0) */
	int lockSuccess = atoi(buffer);
	DEBUG('n', "Client: lockSuccess = %i\n", lockSuccess);

    fflush(stdout);

    return lockSuccess; // CHANGE TO: 0 for lock not deleted or 1 when it is
}

int ClientCreateCV(char *cvName) {
	int randServ = rand() % numberOfServers;
  outPktHdr.to = randServ;
  outMailHdr.to = randServ;
  outMailHdr.from = myMachID;
  
  stringstream ss;
  char *message = new char[MaxMailSize];
  //int timet = time(NULL)%10000000;
  //ss << timet << " ";	//send the timestamp
  ss << "15 " << cvName;
  message = (char*)ss.str().c_str();
  printf("%s\n", message);
  // Syscall ID, lock index, name

  outMailHdr.length = strlen(message) + 1;
  outPktHdr.from = myMachID;
  
  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Create CV postOffice send failed. No server found.\n");
      return -1;
    }

    // Wait for the first message from the other machine
    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);
    
    // Parse the message; looking for an int
	int result = atoi(buffer);

    fflush(stdout);

    return result;
}

int ClientWait(char *lockName, char *cvName) {
	int randServ = rand() % numberOfServers;
  outPktHdr.to = randServ;
  outMailHdr.to = randServ;
  outMailHdr.from = myMachID;

  stringstream ss;
  char *message = new char[MaxMailSize];
  //int timet = time(NULL)%10000000;
  //ss << timet << " ";	//send the timestamp
  ss << "18 " << cvName << " " << lockName << " " << outMailHdr.from;
  strcpy(message, (char*)ss.str().c_str());
  // Syscall ID, lock index, CV Index

  outMailHdr.length = strlen(message) + 1;
  outPktHdr.from = myMachID;
  
  printf("%s\n", message);
  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Wait on CV postOffice send failed. No server found.\n");
      return -1;
    }

	ClientReleaseLock(lockName);

    // Wait for the first message from the other machine
    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);
    
    // Parse the message; looking for an int
    int result = atoi(buffer);

    fflush(stdout);

	ClientAcquireLock(lockName);

    return result; // 0 means bad information, 1 means a successful wait
}

int ClientSignal(char *lockName, char *cvName) {
	int randServ = rand() % numberOfServers;
  outPktHdr.to = randServ;
  outMailHdr.to = randServ;
  outMailHdr.from = myMachID;


  stringstream ss;
  char *message = new char[MaxMailSize];
  //int timet = time(NULL)%10000000;
  //ss << timet << " ";	//send the timestamp
  ss << "16 " << cvName << " " << lockName << " " << myMachID;
  strcpy(message, (char*)ss.str().c_str());
  // Syscall ID, lock index, CV Index

  outMailHdr.length = strlen(message) + 1;
  outPktHdr.from = myMachID;

  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Signal on CV postOffice send failed. No server found.\n");
      return -1;
    }

    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);
    
    // Parse the message; looking for an int
    int result = atoi(buffer);

    fflush(stdout);

    return result;
}

int ClientBroadcast(char *lockName, char *cvName) {
	int randServ = rand() % numberOfServers;
  outPktHdr.to = randServ;
  outMailHdr.to = randServ;
  outMailHdr.from = myMachID;


  stringstream ss;
  char *message = new char[MaxMailSize];
  //int timet = time(NULL)%10000000;
  //ss << timet << " ";	//send the timestamp
  ss << "17 " << cvName << " " << myMachID;
  message = (char*)ss.str().c_str();
  // Syscall ID, lock index, CV Index

  outMailHdr.length = strlen(message) + 1;
  outPktHdr.from = myMachID;

  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Broadcast on CV postOffice send failed. No server found.\n");
      return -1;
    }

    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);
    
    // Parse the message; looking for an int

    int result = atoi(buffer);
	if(result == 0) {
		printf("ERROR IN WAIT\n");
	}

    fflush(stdout);

    return result; // 0 on fail, 1 on success.
}

int ClientDeleteCV(char *lockName, char *cvName) {
	int randServ = rand() % numberOfServers;
  outPktHdr.to = randServ;
  outMailHdr.to = randServ;
  outMailHdr.from = myMachID;

  stringstream ss;
  char *message;
  ss << "19 " << cvName << " " << myMachID;
  message = (char*)ss.str().c_str();
  // Syscall ID, lock index, CV Index

  outMailHdr.length = strlen(message) + 1;
  outPktHdr.from = myMachID;

  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Delete CV postOffice send failed. No server found.\n");
      return -1;
    }

    // Wait for the first message from the other machine
    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);

    // Parse the message; looking for an int

    int result = atoi(buffer);

    fflush(stdout);

    return result; // 0 on fail, 1 on success.   
}

int ClientCreateMV(char *mvName, int arrSize) {
  outPktHdr.to = 0;
  outMailHdr.to = 0;
  outMailHdr.from = 1;

  stringstream ss;
  char *message;
  ss << "26 " << mvName << " " << myMachID << " " << arrSize;
  ss >> message;
  // Syscall ID, lock index, CV Index

  outMailHdr.length = strlen(message) + 1;
  outPktHdr.from = myMachID;

  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Create MV postOffice send failed. No server found.\n");
      return -1;
    }

    // Wait for the first message from the other machine
    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);

    // Parse the message; looking for an int

    stringstream ssr;
    ssr << buffer;
    char *intToBe;
    ssr >> intToBe;

    int result = atoi(intToBe);

    fflush(stdout);

    return result; // 0 on fail, 1 on success.
}

int ClientMVGet(char *mvName, int arrIndex) {
  outPktHdr.to = 0;
  outMailHdr.to = 0;
  outMailHdr.from = 1;

  stringstream ss;
  char *message;
  ss << "27 " << mvName << " " << arrIndex;
  ss >> message;
  // Syscall ID, lock index, CV Index

  outMailHdr.length = strlen(message) + 1;
  outPktHdr.from = myMachID;

  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Create MV postOffice send failed. No server found.\n");
      return -1;
    }

    // Wait for the first message from the other machine
    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);

    // Parse the message; looking for an int

    stringstream ssr;
    ssr << buffer;
    char *intToBe;
    ssr >> intToBe;

    int result = atoi(intToBe);

    fflush(stdout);

    return result; // get value
}

int ClientMVSet(char *mvName, int arrIndex, int newVal) {
  outPktHdr.to = 0;
  outMailHdr.to = 0;
  outMailHdr.from = 1;

  stringstream ss;
  char *message;
  ss << "28 " << mvName << " " << arrIndex << " " << newVal;
  ss >> message;
  // Syscall ID, lock index, CV Index

  outMailHdr.length = strlen(message) + 1;
  outPktHdr.from = myMachID;

  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Create MV postOffice send failed. No server found.\n");
      return -1;
    }

    // Wait for the first message from the other machine
    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);

    // Parse the message; looking for an int

    stringstream ssr;
    ssr << buffer;
    char *intToBe;
    ssr >> intToBe;

    int result = atoi(intToBe);

    fflush(stdout);

    return result; // 0 on fail, 1 on success.
}

int ClientMVDelete(char *mvName) {
  outPktHdr.to = 0;
  outMailHdr.to = 0;
  outMailHdr.from = 1;

  stringstream ss;
  char *message;
  ss << "29 " << mvName;
  ss >> message;
  // Syscall ID, lock index, CV Index

  outMailHdr.length = strlen(message) + 1;
  outPktHdr.from = myMachID;

  // Send the first message
  bool success = postOffice->Send(outPktHdr, outMailHdr, message);

    if ( !success ) {
      printf("Create MV postOffice send failed. No server found.\n");
      return -1;
    }

    // Wait for the first message from the other machine
    postOffice->Receive(outMailHdr.from, &inPktHdr, &inMailHdr, buffer);

    // Parse the message; looking for an int

    stringstream ssr;
    ssr << buffer;
    char *intToBe;
    ssr >> intToBe;

    int result = atoi(intToBe);

    fflush(stdout);

    return result; // 0 on fail, 1 on success.
}
